package
{
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundMixer;
	import flash.media.SoundTransform;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.system.System;
	import flash.utils.ByteArray;
	
	import model.ModelLocator;
	
	import mx.controls.Label;
	import mx.core.Application;
	import mx.core.mx_internal;
	import mx.events.FlexEvent;
	
	import view.KRC;
	import view.Qrc2KmcParser;
	
	public class MusicPlayerClass extends Application
	{
		public var msg:Label;
		private var url_mp3:String;
		private var url_kmc:String;
		private var sound:Sound;
		private var channel:SoundChannel;
		private var position:int = 0;
		private var duration:int = 0;
		private var paused:Boolean = false;
		private var stf:SoundTransform;
		private var kmc:KMC;
		private var _model:ModelLocator;
		
		public function MusicPlayerClass()
		{
			_model = ModelLocator.getInstance();
		}
		
		public function onInit():void
		{
			_model.main = MusicPlayer(document);
			kmc = new KMC();
			_model.lyricPanel.rawChildren.addChild( kmc );
			kmc.x = (_model.lyricPanel.width - kmc.width)/2;
			kmc.y = (_model.lyricPanel.height - kmc.height)/2;
			stf = new SoundTransform();
			System.useCodePage = true;
			_model.playerPanel.bt_play.addEventListener(MouseEvent.CLICK, playHandler);
			_model.playerPanel.seekbar.addEventListener(MouseEvent.CLICK, seekHandler);
			_model.playerPanel.bt_pause.addEventListener(MouseEvent.CLICK, pauseHandler);
			_model.playerPanel.bt_stop.addEventListener(MouseEvent.CLICK, stopHandler);
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, loaded);
			loader.addEventListener(IOErrorEvent.IO_ERROR, errord);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errord);
			loader.load(new URLRequest("assets/config.xml"));
			
		}
		
		private function loaded(e:Event):void 
		{
			try 
			{
				var xml:XMLList = new XMLList(e.target.data);
			}
			catch (e:Error) 
			{
				output(e);
			}
			url_mp3 = xml.@mp3;
			url_kmc = xml.@kmc;
		}
		
		private function errord(e:Event):void 
		{
			output(e);
		}
		
		private function seekHandler(e:MouseEvent):void {
			//				var tw:Number = seekbar.value;
			//				var tx:Number = seekbar.bg.mouseX;
			//				var tx:Number = seekbar.getXFromValue(tw);
			//				seekbar.value = tx;
			//				var per:Number = tx / tw;
			//				seek(per);
			seek(e.localX/_model.playerPanel.seekbar.width);
		}
		
		private function seek(per:Number):void {
			//没有长度不能搜索
			if (!sound || !sound.length) {
				return;
			}
			position = duration * per * 1000;
			start();
		}
		
		private function playHandler(e:MouseEvent):void {
			if (paused && sound) {
				start();
			} else {
				sound = new Sound();
				sound.load(new URLRequest(url_mp3));
				sound.addEventListener(Event.OPEN, openHandler);
				sound.addEventListener(IOErrorEvent.IO_ERROR, errord);
				sound.addEventListener(Event.COMPLETE, loadedHandler);
				sound.addEventListener(ProgressEvent.PROGRESS, progressHandler);
				output("connecting ...");
				kmc.load(url_kmc);
			}
		}
		private function pauseHandler(e:MouseEvent):void {
			if (!sound) {
				return;
			}
			if (paused) {
				start();
				paused = false;
				return;
			}
			removeEventListener(Event.ENTER_FRAME, timeHandler);
			position = channel.position;
			channelStop();
			paused = true;
			output("paused");
		}
		private function stopHandler(e:MouseEvent):void {
			removeEventListener(Event.ENTER_FRAME, timeHandler);
			paused = false;
			position = 0;
			duration = 0;
			output("stopped");
			_model.playerPanel.seekbar.value = 0;
			showTime();
			channelStop();
			if (sound) {
				sound.removeEventListener(Event.OPEN, openHandler);
				sound.removeEventListener(Event.COMPLETE, loadedHandler);
				sound.removeEventListener(IOErrorEvent.IO_ERROR, errord);
				sound.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
				try {
					sound.close();
				} catch (e:Error) {
				}
				sound = null;
			}
			kmc.stop();
		}
		
		private function channelStop():void {
			if (channel) {
				channel.stop();
				channel.removeEventListener(Event.SOUND_COMPLETE, completeHandler);
			}
		}
		
		private function completeHandler(e:Event):void {
			paused = false;
			position = 0;
		}
		private function openHandler(e:Event):void {
			position = 0;
			start();
		}
		private function start():void {
			output("playing");
			if (position > sound.length) {
				position = sound.length;
			}
			channelStop();
			channel = sound.play(position);
			channel.addEventListener(Event.SOUND_COMPLETE, completeHandler);
			stf.volume = 1;
			channel.soundTransform = stf;
			addEventListener(Event.ENTER_FRAME, timeHandler);
		}
		
		private function progressHandler(e:ProgressEvent):void {
			var bt:Number = sound.bytesTotal;
			var bl:Number = sound.bytesLoaded;
			//下载进度
			var pre:Number = 0;
			if (bt > 0) {
				pre = bl / bt;
			}
			var per:String = "loading ... " + Math.round(pre * 100) + "%";
			output(per);
			if (pre > 0 && sound.length) {
				var len:Number = Math.floor(sound.length * 0.001 / pre);
				if (len > duration) {
					duration = len;
				}
			}
		}
		
		private function loadedHandler(e:Event):void {
			if (sound.length) {
				duration = sound.length * 0.001;
				output("loaded");
			}
		}
		
		private function timeHandler(e:Event):void {
			position = channel.position;
			kmc.update(position);
			//播放位置 单位秒
			showTime();
			//
			var tx:Number = position * 0.001 / duration;
			_model.playerPanel.seekbar.value = tx*100;
			
			updateGraph();
		}
		
		private const WAVE_COLOR:uint = 0x0000FF;
		private const WAVE_WIDTH:uint = 200;
		private const WAVE_HEIGHT:uint = 70;
		
		private function updateGraph():void 
		{
			var spectrumData:ByteArray = getSoundSpectrum();
			_model.playerPanel.soundSpectrumCan.graphics.clear();
			_model.playerPanel.soundSpectrumCan.graphics.beginFill(WAVE_COLOR);
			var ratio:Number = WAVE_WIDTH/512;
			var x:Number = 0;
			var y:Number = WAVE_HEIGHT;
			var value:Number;
			var position:uint;
			var i:int = -1;
			while (++i < 512) {
				value = Math.ceil(WAVE_HEIGHT*spectrumData.readFloat());
				if (i < 256) {
					position = i*2;
				} else {
					position = (i%256)*2+1;
				}
				_model.playerPanel.soundSpectrumCan.graphics.drawRect(x+position*ratio, y, 1, -value);
			}
		}
		
		private function showTime():void {
			var seconds:Number = position * 0.001;
			_model.playerPanel.time.text = sTime(seconds, duration);
		}
		private function sTime(p:Number, d:Number):String {
			return zero(p/60) + ":" + zero(p%60) + " / " + zero(d/60) + ":" + zero(d%60);
		}
		//补0
		private function zero(n:Number):String {
			var str:String = String(int(n));
			if (str.length < 2) {
				str = "0" + str;
			}
			return str;
		}
		
		private function output(str:*):void 
		{
			msg.text = str;
		}
		
		public function get volume():Number
		{
			return channel.soundTransform.volume*100;
		}      

		public function set volume(volume:Number):void
		{
			trace("setVolume: " + volume.toFixed(2));
			var transform:SoundTransform = channel.soundTransform;
			transform.volume = volume/100;
			channel.soundTransform = transform;

//			var trans:SoundTransform = new SoundTransform(volume/100,0);
//			if(channel!=null)
//			{
//				channel.soundTransform = trans;
//			}
			
		}
		
		public function getSoundSpectrum(fftMode:Boolean=true, stretchFactor:int=0):ByteArray {
			var spectrumData:ByteArray = new ByteArray();
			SoundMixer.computeSpectrum(spectrumData, fftMode, stretchFactor);
			return spectrumData;
		}
		
	}
}